package com.chencs.webmvc.rest;

import java.net.URI;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

@Component
@RefreshScope
public class RestFullTemplate {
//	public static final String APP_TOKEN = "appToken";
//	public static final String APP_ID = "appId";
//	public static final String DS_KEY = "dsKey";

	Logger logger = LoggerFactory.getLogger(RestTemplate.class);
	@Autowired
	LoadBalancerClient loadBalancer;
	@Autowired
	DiscoveryClient discoveryClient;

	@Value("${gateway.serviceId}")
	String gatewayServiceId;

	@Value("${gateway.appToken}")
	String appToken;

	@Value("${gateway.appId}")
	String appId;

	@Resource(name="nativeRestTemplate")
	RestTemplate restTemplate;

	public String getAgentBelong(){
		return "zibo";
	}

	public HttpHeaders createHeader(){
		HttpHeaders headers = new HttpHeaders();
		headers.add("Accept", "application/json");
		headers.add("Accpet-Encoding", "gzip");
		headers.add("Content-Encoding", "UTF-8");
		headers.add("Content-Type", "application/json; charset=UTF-8");
//		headers.add(APP_TOKEN, appToken);
//		headers.add(APP_ID, appId);
		return headers;
	}

	public String serviceUrl(String uri) {
		String dev = System.getProperty("spring.profiles.active");
		logger.info("gatewayServiceId ");
		logger.info("gatewayServiceId = {}", gatewayServiceId);
		if("pro".equals(dev) || "uat".equals(dev) || "sit".equals(dev) || "dev".equals(dev)) {
			ServiceInstance si = loadBalancer.choose(gatewayServiceId);
			uri = "http://"+ si.getHost() + ":" + si.getPort() + "/" + uri;
		} else if(dev == null){

			ServiceInstance remoteSI = null;
			if(uri.startsWith("/")) {
				uri = uri.substring(1);
			}
			String serviceId = uri.substring(0, uri.indexOf("/"));
			logger.debug("serviceId:{}", serviceId);
			List<ServiceInstance> list = discoveryClient.getInstances(serviceId);
			for(ServiceInstance si : list) {
				logger.debug("services:" + serviceId + ":getHost()=" + si.getHost() + ":getPort()=" + si.getPort() + ":getServiceId()=" + si.getServiceId()+ ":getUri()=" + si.getUri() + ":getMetadata()=" + si.getMetadata());
				remoteSI = si;
				break;
			}
			if(serviceId.equals("service-security")) {
				//安全认证用， 此处不用
				//uri = "http://10.228.56.151:8001/"+uri.substring(uri.indexOf("/"));
			} else {
				if(remoteSI==null && list.size()>0){
					remoteSI = list.get(0);
				}
				if(remoteSI==null){
					throw new RuntimeException("无可连接的微服务");
				}
				uri = "http://"+remoteSI.getServiceId()+":"+remoteSI.getPort()+"/"+uri.substring(uri.indexOf("/"));
			}

			logger.info("uri", uri);
		}
		return uri;
	}

	public String getSurfix(String url) {
		return (url.contains("?")?"&":"?") + "appToken=" + appToken + "&appId=" + appId+ "&dsKey=" + getAgentBelong();
	}

	public String post(String url, Object... args)
			throws Exception {
		HttpHeaders headers = createHeader();
		HttpEntity<String> formEntity = new HttpEntity<String>(null, headers);
		url = serviceUrl(url);
		logger.info("post uri: {}, array args:{}", url, args);
		return restTemplate.postForObject(url, formEntity, String.class, args);
	}

	public <T> T postForObject(String url, Class<T> clazz, Object msg, Object... args) {
		HttpHeaders headers = createHeader();
		HttpEntity<Object> formEntity = new HttpEntity<Object>(msg, headers);
		url = serviceUrl(url);
		logger.info("postForObject uri: {}, clazz:{}, body:{}, args:{}", url, clazz.getName(), msg, args);
		return restTemplate.postForObject(url, formEntity, clazz, args);
	}

	public void put(String url, Object msg) {
		HttpHeaders headers = createHeader();
		HttpEntity<Object> formEntity = new HttpEntity<Object>(msg, headers);
		url = serviceUrl(url);
		logger.info("put uri:{}, msg:{}", url, msg);
		restTemplate.put(URI.create(url), formEntity);
	}

	public void put(String url, Object msg, Map<String,?> urlVariables) {
		HttpHeaders headers = createHeader();
		HttpEntity<Object> formEntity = new HttpEntity<Object>(msg, headers);
		url = serviceUrl(url);
		logger.info("put uri:{}, msg:{}, map args:{}", url, msg, urlVariables);
		restTemplate.put(url, formEntity, urlVariables);
	}

	public void put(String url, Object msg, Object... args) {
		HttpHeaders headers = createHeader();
		HttpEntity<Object> formEntity = new HttpEntity<Object>(msg, headers);
		url = serviceUrl(url);
		logger.info("put uri:{}, msg:{}, array args:{}", url, msg, args);
		restTemplate.put(url, formEntity, args);
	}


	public <T> T getForObject(String url, Class<T> clazz) {
		url = serviceUrl(url) + getSurfix(url);
		logger.info("getForObject uri:{}, clazz:{}", url, clazz.getName());
		return restTemplate.getForObject(URI.create(url), clazz);
	}
	/**
	 *
	 */
	public <T> T getForObject(String url, Class<T> clazz, Object... args) {
		url = serviceUrl(url) + getSurfix(url);
		logger.info("getForObject uri:{}, clazz:{}, array args:{}", url, clazz.getName(), args);
		return restTemplate.getForObject(url, clazz,  args);
	}

	public <T> T getForObject(String url, Class<T> clazz, Map<String,?> args) {
		url = serviceUrl(url) + getSurfix(url);
		logger.info("getForObject uri:{}, clazz:{}, map args:{}", url, clazz.getName(), args);
		return restTemplate.getForObject(url, clazz,  args);
	}


}
